﻿using System;
using System.CodeDom;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace Msdn5.Framework
{
    /// <summary>
    /// 针对Object对象的反射帮助类
    /// </summary>
    public static class ObjectHelper
    { 
        /// <summary>
        /// 从字符串调用指定的类型转换器转换内容
        /// "111".Convert<double>();
        /// "True".Convert<bool>();
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="input">输入的内容</param>
        /// <returns>转换后的内容</returns>
        public static T ConvertTo<T>(this string input)
        {
            try
            {
                var converter = TypeDescriptor.GetConverter(typeof(T));
                if (converter != null)
                {
                    return (T)converter.ConvertFromString(input);
                }
                return default(T);
            }
            catch (Exception)
            {
                return default(T);
            }
        }

        /// <summary>
        /// 从字符串调用指定的类型转换器转换内容
        /// "111".Convert<double>();
        /// "True".Convert<bool>();
        /// </summary>
        /// <param name="input">输入的内容</param>
        /// <param name="type">类型</param>
        /// <returns>转换后的内容</returns>
        public static object ConvertTo(this string input, Type type)
        {
            try
            {
                var converter = TypeDescriptor.GetConverter(type);
                if (converter != null)
                {
                    return converter.ConvertFromString(input);
                }
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }





        /// <summary>
        /// 使用反射设置属性值.
        /// </summary>
        /// <param name="o">需要设置的对象</param>
        /// <param name="pname">属性名</param>
        /// <param name="val">值</param>
        public static void SetPropertyValue(this object o, string pname, object val)
        {
            Type Ts = o.GetType();
            var prop = Ts.GetProperty(pname, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.GetProperty);
            if (prop == null)
            {
                return;
            }
            object v = Convert.ChangeType(val, prop.PropertyType);
            prop.SetValue(o, v, null);
        }
        /// <summary>
        /// 反射获取属性值,且使用排序字典
        /// </summary>
        /// <param name="o">对象</param>
        /// <returns>排序后的属性/值</returns>
        public static SortedDictionary<string, string> GetPropertysToSortedDictionary(this object o)
        {
            SortedDictionary<string, string> stdic = new SortedDictionary<string, string>();
            PropertyInfo[] propertyInfos = o.GetType().GetProperties();
            for (int i = 0; i < propertyInfos.Length; i++)
            {
                PropertyInfo info = propertyInfos[i];
                string key = info.Name;
                string val = null;
                //var getter = info.GetGetMethod(false);
                //getter.Invoke(o, null);
                object oval = info.GetValue(o);
                //基元类型或者字符串则直接取值. 如果是类,且不是基元类型,则直接取其Json字符串
                if (info.PropertyType.IsPrimitive || info.PropertyType == typeof(string))
                {
                    val = oval?.ToString();
                }
                else if (info.PropertyType.IsClass && !info.PropertyType.IsPrimitive)
                {
                    val = oval?.ToJson();
                    //如果需要继续递归子类 开放下面代码
                    /*
                   if (oval != null)
                   {
                       var tmp = oval.GetPropertysToSortedDictionary();
                       foreach (var itemt in tmp)
                       {
                           stdic.Add(itemt.Key, itemt.Value);
                       }
                   }
                   continue;  
                   */
                }
                if (!stdic.ContainsKey(key))
                {
                    stdic.Add(key, val);
                }
                else
                {
                    stdic[key] = val;
                }
            }
            return stdic;
        }
         
        /// <summary>
        /// 字典拼接为字符串
        /// </summary>
        /// <param name="pairs">字典</param>
        /// <param name="pstr">key和val之间的符号默认为=</param>
        /// <param name="estr">每一组数据之间的符号默认为&</param>
        /// <returns>字符串</returns>
        public static string ToStr(this IDictionary<string, string> pairs, string pstr = "=", string estr = "&")
        {
            return string.Join(estr, pairs.Select(x => $"{x.Key}{pstr}{x.Value}")); 
        }
        /// <summary>
        /// 生成从属性创建ListViewItem
        /// </summary>
        /// <param name="item">要创建的对象</param>
        /// <returns>生成的代码</returns>
        public static string GetPropertysToAddOrUpdateListViewItem(this object item)
        {
            var itempro = item.GetPropertysToSortedDictionary();
            StringBuilder builer = new StringBuilder();
            var strs = item.ToString().Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
            var name = strs.Length > 1 ? strs[strs.Length - 1] : strs[0];
            builer.Append($"void AddOrUpdate{name}Item({name} Item)").AppendLine();
            builer.Append($"        {{").AppendLine();
            builer.Append($"            this.BeginInvoke(new Action(delegate").AppendLine();
            builer.Append($"            {{ ");
            builer.Append("             var name = $\"lvi_{Item.Index}\";").AppendLine();
            builer.Append($"            if (!lv.Items.ContainsKey(name))").AppendLine();
            builer.Append($"            {{").AppendLine();
            builer.Append($"            ListViewItem lvi = new ListViewItem();//不存在则新增").AppendLine();
            builer.Append($"            lvi.Name = name;").AppendLine();
            builer.Append($"            lvi.Text = Item.Index.ToString();").AppendLine();
            builer.Append($"            lvi.Tag = Item;").AppendLine();
            builer.Append($"            ListViewItem.ListViewSubItem subItem;").AppendLine().AppendLine();
            foreach (var it in itempro)
            {
                builer.Append($"            subItem = new ListViewItem.ListViewSubItem();").AppendLine();
                builer.Append($"            subItem.Name = \"{it.Key}\";").AppendLine();
                builer.Append($"            subItem.Text = Item.{it.Key}.ToString(); ").AppendLine();
                builer.Append($"            lvi.SubItems.Add(subItem);").AppendLine().AppendLine();
            }
            builer.Append($"   lv.Items.Add(lvi);").AppendLine();
            builer.Append($"   lv.Items[lv.Items.Count - 1].EnsureVisible();//滚动到新行").AppendLine();
            builer.Append($"           }}else{{").AppendLine();
            builer.Append($"                    if (lv.Items[name] != null)").AppendLine();
            builer.Append($"                    {{").AppendLine();
            builer.Append($"                    var lvi = lv.Items[name];").AppendLine();
            builer.Append($"                    if (lvi.SubItems != null)").AppendLine();
            builer.Append($"                    {{").AppendLine();
            foreach (var it in itempro)
            {
                builer.Append($"                lvi.SubItems[\"{it.Key}\"].Text = Item.{it.Key}.ToString();").AppendLine();
            }
            builer.Append($"                    }}").AppendLine();
            builer.Append($"                    lvi.Tag = Item;").AppendLine();
            builer.Append($"                    }}");
            builer.Append($"                }}").AppendLine();
            builer.Append($"           }}));");
            builer.Append($"              }}").AppendLine();
            return builer.ToString();
        }
        /// <summary>
        /// 生成从属性创建ListViewItem
        /// </summary>
        /// <param name="item">要创建的对象</param>
        /// <returns>生成的代码</returns>
        public static string GetPropertysToCreateListViewItem(this object item)
        {
            var itempro = item.GetPropertysToSortedDictionary();
            StringBuilder builer = new StringBuilder();
            var strs = item.ToString().Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
            var name = strs.Length > 1 ? strs[strs.Length - 1] : strs[0];
            builer.Append($"void Add{name}Item({name} Item)").AppendLine();
            builer.Append($"        {{").AppendLine();
            builer.Append("             var name = $\"lvi_{Item.某属性}\";").AppendLine();
            builer.Append($"            if (!lv.Items.ContainsKey(name))").AppendLine();
            builer.Append($"            {{").AppendLine();
            builer.Append($"            ListViewItem lvi = new ListViewItem();").AppendLine();
            builer.Append($"            lvi.Name = name;").AppendLine();
            builer.Append($"            lvi.Text = 第一个显示的属性;").AppendLine();
            builer.Append($"            lvi.Tag = Item;").AppendLine();
            builer.Append($"            ListViewItem.ListViewSubItem subItem;").AppendLine().AppendLine();
            foreach (var it in itempro)
            {
                builer.Append($"            subItem = new ListViewItem.ListViewSubItem();").AppendLine();
                builer.Append($"            subItem.Name = \"{it.Key}\";").AppendLine();
                builer.Append($"            subItem.Text = Item.{it.Key}.ToString(); ").AppendLine();
                builer.Append($"            lvi.SubItems.Add(subItem);").AppendLine().AppendLine();
            }
            builer.Append($"   lv.Items.Add(lvi);").AppendLine();
            builer.Append($"   lv.Items[lv.Items.Count - 1].EnsureVisible();//滚动到新行").AppendLine();
            builer.Append($"        }}").AppendLine();
            builer.Append($"        }}").AppendLine();
            return builer.ToString();
        }
        /// <summary>
        /// 生成从属性修改ListViewItem
        /// </summary>
        /// <param name="item">要创建的对象</param>
        /// <returns>生成的代码</returns>
        public static string GetPropertysToUpdateListViewItem(this object item)
        {
            var itempro = item.GetPropertysToSortedDictionary();
            StringBuilder builer = new StringBuilder();
            var strs = item.ToString().Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
            var name = strs.Length > 1 ? strs[strs.Length - 1] : strs[0];
            builer.Append($"  void Update{name}Item(ListViewItem lvi, {name} Item)").AppendLine();
            builer.Append($"        {{").AppendLine();
            builer.Append($"            lvi.Text = Item.第一个显示的属性;").AppendLine();
            builer.Append($"            if (lvi.SubItems != null) {{").AppendLine();
            foreach (var it in itempro)
            {
                builer.Append($"                lvi.SubItems[\"{it.Key}\"].Text = Item.{it.Key}.ToString();").AppendLine();
            }
            builer.Append($"            }}").AppendLine();
            builer.Append($"            lvi.Tag = Item;").AppendLine();
            builer.Append($"        }}").AppendLine();
            return builer.ToString();
        }

        /// <summary>
        /// 生成Winform增删改Listview
        /// </summary>
        /// <param name="item">实体对象</param>
        /// <returns>生成的代码</returns>
        public static string ToListView(this object item)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendLine(item.GetPropertysToCreateListViewItem());
            builder.AppendLine(item.GetPropertysToUpdateListViewItem());
            builder.AppendLine(ListViewCURD());
            return builder.ToString();
        }

        public static string ListViewCURD()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append($"  private void 新增软件ToolStripMenuItem_Click(object sender, EventArgs e)").AppendLine();
            builder.Append($"        {{").AppendLine();
            builder.Append($"            FrmData data = new FrmData();").AppendLine();
            builder.Append($"            data.ShowDialog();").AppendLine();
            builder.Append($"            data.Item.Index = lv.Items.Count + 1;").AppendLine();
            builder.Append($"            if (data.Item.Name.NotNullOrEmpty() && data.Item.DownloadUrl.NotNullOrEmpty() && data.Item.Ver.NotNullOrEmpty())").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                AddConfigItemItem(data.Item);").AppendLine();
            builder.Append($"            }}").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        }}").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        private void 编辑条目ToolStripMenuItem_Click(object sender, EventArgs e)").AppendLine();
            builder.Append($"        {{").AppendLine();
            builder.Append($"            if (lv.SelectedItems.Count > 0)").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                var lvi = lv.SelectedItems[0];").AppendLine();
            builder.Append($"                if (lvi?.Tag is ConfigItem item)").AppendLine();
            builder.Append($"                {{").AppendLine();
            builder.Append($"                    FrmData data = new FrmData();").AppendLine();
            builder.Append($"                    data.Item = item;").AppendLine();
            builder.Append($"                    data.ShowDialog();").AppendLine();
            builder.Append($"                    UpdateConfigItemItem(lvi, item);").AppendLine();
            builder.Append($"                    return;").AppendLine();
            builder.Append($"                }}").AppendLine();
            builder.Append($"            }}").AppendLine();
            builder.Append($"            MessageBox.Show(\"请先选中条目!\", \"错误\", MessageBoxButtons.OK, MessageBoxIcon.Error);").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        }}").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        private void 删除选中ToolStripMenuItem_Click(object sender, EventArgs e)").AppendLine();
            builder.Append($"        {{").AppendLine();
            builder.Append($"            if (lv.SelectedItems.Count > 0)").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                var lvi = lv.SelectedItems[0];").AppendLine();
            builder.Append($"                if (MessageBox.Show(\"确认删除本条数据?\", \"询问\", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)").AppendLine();
            builder.Append($"                {{").AppendLine();
            builder.Append($"                    lv.Items.Remove(lvi);").AppendLine();
            builder.Append($"                }}").AppendLine();
            builder.Append($"                return;").AppendLine();
            builder.Append($"            }}").AppendLine();
            builder.Append($"            MessageBox.Show(\"请先选中条目!\", \"错误\", MessageBoxButtons.OK, MessageBoxIcon.Error);").AppendLine();
            builder.Append($"        }}").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        private void 清空所有ToolStripMenuItem_Click(object sender, EventArgs e)").AppendLine();
            builder.Append($"        {{").AppendLine();
            builder.Append($"            if (MessageBox.Show(\"确认清空所有数据?\", \"询问\", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                lv.Items.Clear();").AppendLine();
            builder.Append($"            }}").AppendLine();
            builder.Append($"        }}").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        private void 生成配置文件ToolStripMenuItem_Click(object sender, EventArgs e)").AppendLine();
            builder.Append($"        {{").AppendLine();
            builder.Append($"            configItems = new List<ConfigItem>();").AppendLine();
            builder.Append($"            for (int i = 0; i < lv.Items.Count; i++)").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                if (lv.Items[i].Tag is ConfigItem item)").AppendLine();
            builder.Append($"                {{").AppendLine();
            builder.Append($"                    configItems.Add(item);").AppendLine();
            builder.Append($"                }}").AppendLine();
            builder.Append($"            }}").AppendLine();
            builder.Append($"            GlobalConfig.GetEnData(configItems.ToJson()).WriteJsonFile(\"Config.json\", x =>").AppendLine();
            builder.Append($"            {{").AppendLine();
            builder.Append($"                if (x != null)").AppendLine();
            builder.Append($"                {{").AppendLine();
            builder.Append($"                    MessageBox.Show($\"文件保存失败\\r\\n{{x.Message}}\", \"错误\", MessageBoxButtons.OK, MessageBoxIcon.Error);").AppendLine();
            builder.Append($"                }}").AppendLine();
            builder.Append($"            }});").AppendLine();
            builder.Append($"            MessageBox.Show($\"文件保存成功!\", \"提示\", MessageBoxButtons.OK, MessageBoxIcon.Information);").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"            filePath.OpenDir();").AppendLine();
            builder.Append($"").AppendLine();
            builder.Append($"        }}");
            return builder.ToString();//拼接后的结果
        }
    }
}
